/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.hugoo.core.db.mo;

import com.hugoo.core.util.TL;
import java.io.BufferedReader;
import java.math.BigDecimal;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import oracle.sql.Datum;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author hugoo
 */
public class DCV {
    
    protected static final Log log = LogFactory.getLog(DCV.class);
    
    public static String getValue(ResultSet rs, String key) {
        if (TL.isEmpty(key)) {
            log.warn("警告：读取数据库的字段不能为空！");
            return "";
        }
        Object obj = null;
        String ky = key.toUpperCase();
        try {
            obj = rs.getObject(ky);
        } catch (SQLException ex) {
            log.warn("读取字段[" + ky + "]出现异常", ex);
        }
        return getValue(obj);
    }
    
    public static String getValueForXml(Object obj) {
        return new RowData(obj).getXmlVal();
    }
    
    public static String getValueForJson(Object obj) {
        //.replaceAll("[\r|\n]", ""))
        return new RowData(obj).getJsonVal();
    }
    
    public static String getValue(Object obj) {
        return new RowData(obj).getString();
    }
    
    
    static class RowData {
        
        enum TYPE {
            
            NUM, STR, DATE, CLOB,
            OTH, EMPTY
        }
        private TYPE t = TYPE.EMPTY;
        private Number num;
        private String str;
        private Date date;
        private Clob cb;
        private Object object;
        
        RowData(ResultSet rs, String key) {
            Object obj;
            try {
                obj = rs.getObject(key);
                init(obj);
            } catch (SQLException ex) {
                log.warn("读取字段[" + key + "]出现异常!", ex);
            }
            
        }
        
        RowData(Object obj) {
            init(obj);
        }
        
        private void init(Object obj) {
            try {
                if (obj != null) {
                    if (obj instanceof String) {
                        str = (String) obj;
                        t = TYPE.STR;
                    } else if (obj instanceof Number) {
                        num = (Number) obj;
                        t = TYPE.NUM;
                    } else if (obj instanceof Date) {
                        date = (Date) obj;
                        t = TYPE.DATE;
                    } else if (obj instanceof Clob) {
                        cb = (Clob) obj;
                        t = TYPE.CLOB;
                    } else {
                        object = obj;
                        t = TYPE.OTH;
                    }
                }
            } catch (Exception e) {
                log.warn("未知异常，请管理员手动分析！", e);
            }
        }
        
        String getXmlVal() {
            return escape(getString());
        }
        
        String getJsonVal() {
            return quote(getString());
        }
        
        String getString() {
            if (TYPE.EMPTY == t) {
                return "";
            } else if (t == TYPE.STR) {
                return str;
            } else if (TYPE.CLOB == t) {
                return getClobStr();
            } else if (TYPE.NUM == t) {
                return getFmtNum();
            } else if (TYPE.DATE == t) {
                return getFmtDate();
            } else {
                if (object instanceof Datum) {
                    try {
                        return ((Datum) object).stringValue();
                    } catch (SQLException e) {
                        log.error("读取Datum类型出错！", e);
                        return "";
                    }
                }
                return object.toString();
            }//com@fastersoft6903244m370t

        }
        
        private void initNum() {
            if (num == null && TYPE.EMPTY != t) {
                if (TYPE.STR == t) {//本处暂只支持字符串转成数值
                    str = str.replaceAll(",", "");
                    if (str.matches("^((-?\\d+.?\\d*)([Ee]{0,1}(-?\\d+))?)$")) {
                        num = new BigDecimal(str);
                    } else {
                        log.info("字符串[" + str + "]无法转换为数值。");
                    }
                }
            }
        }

        /**
         * 用于解决XML HTML等标识文件的数据显示问题
         *
         * @param string
         * @return
         */
        private String escape(String string) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0, length = string.length(); i < length; i++) {
                char c = string.charAt(i);
                switch (c) {
                    case '&':
                        sb.append("&amp;");
                        break;
                    case '<':
                        sb.append("&lt;");
                        break;
                    case '>':
                        sb.append("&gt;");
                        break;
                    case '"':
                        sb.append("&quot;");
                        break;
                    case '\'':
                        sb.append("&apos;");
                        break;
                    default:
                        sb.append(c);
                }
            }
            return sb.toString();
        }
        
        private String quote(String string) {
            if (string == null || string.length() == 0) {
                return "\"\"";
            }
            
            char b;
            char c = 0;
            String hhhh;
            int i;
            int len = string.length();
            StringBuilder sb = new StringBuilder();
            sb.append('"');
            for (i = 0; i < len; i += 1) {
                b = c;
                c = string.charAt(i);
                switch (c) {
                    case '\\':
                    case '"':
                        sb.append('\\').append(c);
                        break;
                    case '/':
                        if (b == '<') {
                            sb.append('\\');
                        }
                        sb.append(c);
                        break;
                    case '\b':
                        sb.append("\\b");
                        break;
                    case '\t':
                        sb.append("\\t");
                        break;
                    case '\n':
                        sb.append("\\n");
                        break;
                    case '\f':
                        sb.append("\\f");
                        break;
                    case '\r':
                        sb.append("\\r");
                        break;
                    default:
                        if (c < ' ' || (c >= '\u0080' && c < '\u00a0')
                                || (c >= '\u2000' && c < '\u2100')) {
                            sb.append("\\u");
                            hhhh = Integer.toHexString(c);
                            sb.append("0000", 0, 4 - hhhh.length());
                            sb.append(hhhh);
                        } else {
                            sb.append(c);
                        }
                }
            }
            sb.append('"');
            return sb.toString();
        }
        
        Long getLong() {
            initNum();
            if (num == null) {
                return null;
            }
            return num.longValue();
        }
        
        Integer getInteger() {
            initNum();
            if (num == null) {
                return null;
            }
            return num.intValue();
        }
        
        Short getShort() {
            initNum();
            if (num == null) {
                return null;
            }
            return num.shortValue();
        }
        
        Double getDouble() {
            initNum();
            if (num == null) {
                return null;
            }
            return num.doubleValue();
        }
        
        Float getFloat() {
            initNum();
            if (num == null) {
                return null;
            }
            return num.floatValue();
        }
        
        BigDecimal getBigDecimal() {
            initNum();
            if (num == null) {
                return null;
            }
            return (BigDecimal) num;
        }
        
        Date getDate() {
            if (t == TYPE.DATE) {
                return date;
            } else if (t == TYPE.STR) {
                //本处暂时不实现字符串转日期类型
                log.warn("本处暂时不实现字符串转日期类型");
            }
            return null;
        }
        
          private String getFmtNum() {
            if (num == null) {
                return "";
            }
            //本处格式化数值数据
            return TL.numFmt(num, TL.NumFmt.NUM);
        }

        private String getFmtDouble() {
            if (num == null) {
                return "";
            }
            //本处格式化数值数据
            return TL.numFmt(num, TL.NumFmt.DBL2);
        }

        private String getFmtPct() {
            if (num == null) {
                return "";
            }
            //本处格式化数值数据
            return TL.numFmt(num, TL.NumFmt.PCT);
        }

        private String getFmtSplNum() {
            if (num == null) {
                return "";
            }
            //本处格式化数值数据
            return TL.numFmt(num, TL.NumFmt.DBL2);
        }
        
        private String getFmtDate() {
            //本处格式化数值数据
            return TL.format(date, "yyyy-MM-dd HH:mm:ss");
        }
        
        private String getClobStr() {
            BufferedReader br = null;
            try {
                if (cb == null || cb.length() < 1) {
                    return "";
                }
                br = new BufferedReader(cb.getCharacterStream());
                StringBuilder sb = new StringBuilder();
                do {
                    sb.append(br.readLine());
                } while (br.ready());
                return sb.toString();
            } catch (Exception e) {
                log.warn("读取Clob字段值出现异常！", e);
            } finally {
                TL.close(br);
            }
            return "EPS201:READ ERROR!";
        }
    }

    /**
     * 得到 BigDecimal 类型的值
     *
     * @param key 字段名
     * @return BigDecimal 类型的值
     */
    public static BigDecimal getBigDecimal(ResultSet rs, String key) {
        return new RowData(rs, key).getBigDecimal();
    }

    /**
     * 得到 Long 类型的值
     *
     * @param key 字段名
     * @return Long 类型的值
     */
    public static Long getLong(ResultSet rs, String key) {
        return new RowData(rs, key).getLong();
    }

    /**
     * 得到 Integer 类型的值
     *
     * @param key 字段名
     * @return Integer 类型的值
     */
    public static Integer getInteger(ResultSet rs, String key) {
        return new RowData(rs, key).getInteger();
    }

    /**
     * 得到 Short 类型的值
     *
     * @param key 字段名
     * @return Short 类型的值
     */
    public static Short getShort(ResultSet rs, String key) {
        return new RowData(rs, key).getShort();
    }

    /**
     * 得到 Double 类型的值
     *
     * @param key 字段名
     * @return Double 类型的值
     */
    public static Double getDouble(ResultSet rs, String key) {
        return new RowData(rs, key).getDouble();
    }
    
    public static Float getFloat(ResultSet rs, String key) {
        return new RowData(rs, key).getFloat();
    }
    
    public static Float getFloat(Object obj) {
        return new RowData(obj).getFloat();
    }

    /**
     * 得到 BigDecimal 类型的值
     *
     * @param key 字段名
     * @return BigDecimal 类型的值
     */
    public static BigDecimal getBigDecimal(Object obj) {
        return new RowData(obj).getBigDecimal();
    }

    /**
     * 得到 Long 类型的值
     *
     * @param key 字段名
     * @return Long 类型的值
     */
    public static Long getLong(Object obj) {
        return new RowData(obj).getLong();
    }

    /**
     * 得到 Integer 类型的值
     *
     * @param key 字段名
     * @return Integer 类型的值
     */
    public static Integer getInteger(Object obj) {
        return new RowData(obj).getInteger();
    }

    /**
     * 得到 Short 类型的值
     *
     * @param key 字段名
     * @return Short 类型的值
     */
    public static Short getShort(Object obj) {
        return new RowData(obj).getShort();
    }

    /**
     * 得到 Double 类型的值
     *
     * @param key 字段名
     * @return Double 类型的值
     */
    public static Double getDouble(Object obj) {
        return new RowData(obj).getDouble();
    }
}
